// #ifdef H5
import {
	jsonp
} from 'vue-jsonp'
// #endif
// #ifdef APP-PLUS
import PY from '../../PinYin'
// #endif

let mapKey : string | null = null;
let mapKeyIndex = 0;
let keyArr : string[] = [];

const tGetMapKey = () => mapKey


const requestReject = (reject : (p : { status : number }) => void) =>
	reject({ status: 500 });

type RequestParams = {
	url : string;
	data : Record<string, any>;
};
type RequestData<T> = {
	status : number;
	result : T;
	data : T,
	count : number;
	locations:{lat:number,lng:number}[]
};

const Request = <T = any>({ url, data } : RequestParams) =>
	new Promise<RequestData<T>>((resolve, reject) => {
		// #ifndef H5
		uni.request({
			url,
			data,
			success: (res) => {
				if (res.statusCode == 200) {
					const requestData = res.data as RequestData<T>
					if (requestData.status == 0) {
						resolve(requestData);
					} else if (requestData.status === 120 || requestData.status === 121) {
						reRequest<T>(
							{
								url,
								data,
							},
							requestData.status === 121
						)
							.then((res) => {
								resolve(res);
							})
							.catch(() => requestReject(reject));
					} else {
						console.error("请求错误", res);
						requestReject(reject);
					}
				} else {
					console.error("请求失败");
					requestReject(reject);
				}
			},
			fail: (err) => {
				console.log(err, url);
				requestReject(reject);
			},
		});
		// #endif

		// #ifdef H5
		data['output'] = 'jsonp'
		jsonp(url, data)
			.then((res : RequestData<T>) => {
				if (res.status == 0) {
					resolve(res)
				} else if (res.status === 120 || res.status === 121) {
					reRequest<T>({
						url,
						data,
					}, res.status === 121)
						.then(reRes => {
							resolve(reRes)
						})
						.catch(() => requestReject(reject))
				} else {
					requestReject(reject)
				}
			})
			.catch(() => requestReject(reject))
		// #endif
	});

// 当地图api状态码为120或121时，重新请求api，121代表当前使用的key每日调用量已达到上限，需切换新的key
const reRequest = <T>(
	params : {
		url : string;
		data : Record<string, any>;
	},
	switchKey : boolean
) =>
	new Promise<RequestData<T>>((resolve, reject) => {
		if (switchKey) {
			if (!keyArr.length || mapKeyIndex === keyArr.length - 1) {
				reject("error");
			} else {
				mapKeyIndex++;
				mapKey = keyArr[mapKeyIndex];
			}
		}
		Request<T>(params)
			.then((res) => resolve(res))
			.catch((err) => reject(err));
	});
// 逆地址解析
const tGeolocation = (latitude : number, longitude : number, isGeolocation = true) : Promise<{
	address_component : {
		district : string
		city : string
		province : string
	}
	latitude : number
	longitude : number
	address : string
}> =>
	new Promise((resolve, reject) => {
		let data = {
			key: mapKey,
			location: latitude + ',' + longitude
		}
		if (isGeolocation) {
			Request({
				url: 'https://apis.map.qq.com/ws/geocoder/v1',
				data: {
					...data,
					// #ifdef MP-WEIXIN||MP-ALIPAY || APP-PLUS
					get_poi: 1
					// #endif
				}
			})
				.then(res => {
					let {
						district,
						city,
						province
					} = res.result.address_component
					if (res.result.address_component.ad_level_1) {
						let {
							ad_level_1,
							ad_level_2,
							ad_level_3
						} = res.result.address_component
						district = ad_level_3
						city = ad_level_2
						province = ad_level_1
					}
					let data = {
						address_component: {
							district,
							city,
							province
						},
						latitude,
						longitude,
						address: ''
					}
					uni.setStorageSync('userGeolocation', data)
					resolve(data)
				})
				.catch(err => reject(err))
		} else {
			let _data = {
				address_component: {
					district: '',
					city: '',
					province: '',
				},
				latitude,
				longitude,
				address: ''
			}
			uni.setStorageSync('userGeolocation', _data)
			resolve(_data)
		}

	})
const letters = '*ABCDEFGHJKLMNOPQRSTWXYZ'.split('')

export interface DistrictItem {
	fullname : string
	id:number
	location:{
		lat : number
		lng : number
	}
	
}
export interface SortDistrict {
	letter : string,
	data : DistrictItem[]
}

function pySegSort(arr : DistrictItem[], resolve : (data : Array<SortDistrict>) => void) {
	let zh = '阿八嚓哒妸发旮哈讥咔垃痳拏噢妑七呥扨它穵夕丫帀'.split('')
	let segs = [] // 存放数据
	let res = letters.map(letter => ({
		letter,
		data: [] as DistrictItem[]
	}))
	arr.forEach(item => {
		for (let i in res) {
			// #ifdef APP-PLUS
			let a = PY.ConvertPinyin(item.fullname[0]).substr(0, 1)
			if (res[i].letter === a) {
				res[i].data.push(item)
			}
			// #endif
			// #ifndef APP-PLUS
			if ((!zh[Number(i) - 1] || item.fullname.localeCompare(zh[Number(i) - 1], 'zh-CN') >= 0) && item.fullname
				.localeCompare(zh[i], 'zh-CN') < 0) {
				res[i].data.push(item)
			}
			// #endif
		}
	})
	res.shift()
	resolve(res)
}
// 腾讯地图省市区列表
const tGetDistrict = () : Promise<Array<{
	letter : string,
	data : DistrictItem[]
}>> =>
	new Promise((resolve, reject) => {
		let data = {
			key: mapKey
		}
		Request({
			url: 'https://apis.map.qq.com/ws/district/v1/list',
			data
		})
			.then(res => {
				pySegSort(res.result[1], resolve)
			})
			.catch(() => reject([]))
	})
const tLoadMapScript = (arr : string[]) => {
	if (process.env.NODE_ENV === "development") {
		arr = ["YENBZ-UWUCQ-VIJ5V-G6DCI-7BDO5-RPFBJ"];
	}
	if (arr?.length > 0) {
		keyArr = arr;
		mapKey = keyArr[0];
		mapKeyIndex = 0;

		// #ifdef H5
		let script1 = document.createElement("script");
		script1.type = "text/javascript";
		script1.src = `https://map.qq.com/api/gljs?v=1.exp&key=${mapKey}`;
		document.body.appendChild(script1);
		// #endif
	}
};

// 根据地址信息转换经纬度
const tAddressToLocation = async (address : string) => {
	let data = {
		key: mapKey,
		address,
	};
	const res = await Request<{
		location : {
			lng : number;
			lat : number;
		};
	}>({
		url: "https://apis.map.qq.com/ws/geocoder/v1",
		data,
	})
	return {
		longitude: res.result.location.lng,
		latitude: res.result.location.lat,
	}
};

type NearbyAddressParams = {
	latitude : number
	longitude : number
	keyword ?: string
}
type AddressItem = {
	title : string
	address : string
	location : {
		lat : number
		lng : number
	}
}
// 附近地址列表
const tNearbyAddress = async ({
	latitude, longitude,
	keyword
} : NearbyAddressParams) => {
	let data : Record<string, any> = {
		key: mapKey,
		boundary: `nearby(${latitude},${longitude},5000)`,
		page_size: 20
	}
	if (keyword) {
		data['keyword'] = keyword
	}
	const res = await Request<AddressItem[]>({
		url: 'https://apis.map.qq.com/ws/place/v1/search',
		data
	})
	return res.data.map(item => {
		return {
			...item,
			name: item.title,
			vicinity: item.address,
			formatted_address: "",
			geometry: {
				location: {
					latitude: item.location.lat,
					longitude: item.location.lng
				}
			}
		}
	})
}

// 地址纠正补全
const tCompleteAddress = (address : string) => {
	return new Promise((resolve, reject) => {
		let data = {
			key: mapKey,
			address,
		}
		Request({
			url: 'https://apis.map.qq.com/ws/smart_address/address_complete',
			data
		})
			.then(res => {
				resolve(res.result.completed_address)
			})
			.catch(err => reject(err))
	})
}
// 搜索地址
const tSearchAddress = async ({
	latitude,
	longitude,
	keyword,
	page_index
} : {
	latitude : number,
	longitude : number,
	keyword ?: string,
	page_index ?: number
}) => {
	let data : Record<string, string | number | null> = {
		key: mapKey,
	}
	if (keyword) {
		data['region'] = keyword
		data['keyword'] = keyword
	}
	if (latitude) {
		data['location'] = `${latitude},${longitude}`
	}
	if (page_index) {
		data['page_index'] = page_index
		data['page_size'] = 10
	}

	const res = await Request<AddressItem[]>({
		url: 'https://apis.map.qq.com/ws/place/v1/suggestion',
		data
	})
	if (res?.count) {
		return res.data.map(item => {
			return {
				...item,
				name: item.title,
				vicinity: item.address,
				formatted_address: "",
				geometry: {
					location: {
						latitude: item.location.lat,
						longitude: item.location.lng
					}
				}

			}
		})
	}
	return []
}

// 坐标转换为gcj02系坐标，默认转换wgs84
// type=1 GPS坐标
// type=2 sogou经纬度
// type=3 baidu经纬度
// type=4 mapbar经纬度
// type=6 sogou墨卡托
const tLocationsToGcj02 = async ({
	latitude,
	longitude,
	type = 1
} : {
	latitude : number,
	longitude : number,
	type?:number
}) => {
	let data : Record<string, string | number | null> = {
		key: mapKey,
		type
	}
	if (latitude) {
		data['locations'] = `${latitude},${longitude}`
	}


	const res = await Request({
		url: 'https://apis.map.qq.com/ws/coord/v1/translate',
		data
	})
	return {
		...res,
		latitude: res.locations[0].lat,
		longitude: res.locations[0].lng
	}

}

export {
	tGetMapKey,
	tLoadMapScript,
	tGetDistrict,
	tGeolocation,
	tAddressToLocation,
	tNearbyAddress,
	tCompleteAddress,
	tSearchAddress,
	tLocationsToGcj02
}